package com.foxitcloud.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @Description beanUtil
 * @author xxu
 * @CreateDate 2015年1月13日 下午2:19:10
 */
public class BeanUtil
{
	@SuppressWarnings( "unchecked" )
	public static void copyProperties( Object target, Object source ) throws IllegalArgumentException
	{
		Class sourceClz = source.getClass();
		Class targetClz = target.getClass();
		// 得到Class对象所表征的类的所有属性(包括私有属性)
		Field[] fields = sourceClz.getDeclaredFields();
		for ( int i = 0; i < fields.length; i++ )
		{
			String fieldName = fields[i].getName();
			Field targetField = null;
			try
			{
				// 得到targetClz对象所表征的类的名为fieldName的属性，不存在就进入下次循环
				targetField = targetClz.getDeclaredField( fieldName );
			}
			catch ( SecurityException e )
			{
				e.printStackTrace();
				break;
			}
			catch ( NoSuchFieldException e )
			{
				continue;
			}
			// 判断sourceClz字段类型和targetClz同名字段类型是否相同
			if ( fields[i].getType() == targetField.getType() )
			{
				// 由属性名字得到对应get和set方法的名字
				String getMethodName = "get" + BeanUtil.getMethodName( fieldName );
				String setMethodName = "set" + BeanUtil.getMethodName( fieldName );
				// 由方法的名字得到get和set方法的Method对象
				Method getMethod;
				try
				{
					getMethod = sourceClz.getDeclaredMethod( getMethodName, new Class[] {} );
					Method setMethod = targetClz.getDeclaredMethod( setMethodName, fields[i].getType() );
					// 调用source对象的getMethod方法
					Object result = getMethod.invoke( source, new Object[] {} );
					// 调用target对象的setMethod方法
					setMethod.invoke( target, result );
				}
				catch ( SecurityException e )
				{
					e.printStackTrace();
				}
				catch ( NoSuchMethodException e )
				{
					e.printStackTrace();
				}
				catch ( IllegalArgumentException e )
				{
					e.printStackTrace();
				}
				catch ( IllegalAccessException e )
				{
					e.printStackTrace();
				}
				catch ( InvocationTargetException e )
				{
					e.printStackTrace();
				}
			}
			else
			{
				throw new IllegalArgumentException( "同名属性类型不匹配！" );
			}
		}
	}
	
	/**
	 * 把一个字符串的第一个字母大写、效率是最高的
	 * @param fildeName
	 * @return
	 * @throws Exception
	 * @return String
	 */
	public static String getMethodName( String fildeName )
	{
		byte[] items = fildeName.getBytes();
		items[0] = ( byte ) ( ( char ) items[0] - 'a' + 'A' );
		return new String( items );
	}
	
	public static <T > T convertMap(Class<T> type, Map<String,Object> map)
	            throws IntrospectionException, IllegalAccessException,
	            InstantiationException, InvocationTargetException {
	        BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
	        T obj = type.newInstance(); // 创建 JavaBean 对象

	        // 给 JavaBean 对象的属性赋值
	        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
	        for (int i = 0; i< propertyDescriptors.length; i++) {
	            PropertyDescriptor descriptor = propertyDescriptors[i];
	            String propertyName = descriptor.getName();

	            if (map.containsKey(propertyName)) {
	                // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
	                Object value = map.get(propertyName);

	                Object[] args = new Object[1];
	                args[0] = value;

	                descriptor.getWriteMethod().invoke(obj, args);
	            }
	        }
	        return obj;
	    }
}
